import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.io.*;
import java.net.InetSocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class PublicWeb {

    // 定义OCSP响应文件路径
    private static final String OCSP_RESPONSE_FILE = "../OCSP/ocsp.res";
    // OCSP服务执行命令参数
    private static final List<String> OCSP_CMD = Arrays.asList(
        "java",
        "-cp",
        ".;../SourCode/JarBC18181/*;../OCSP;",
        "SimpleOCSPServer_SM2"
    );
    // 文件路径常量
    private static final String CA_CERT_FILE = "ca.crt";
    private static final String CA_CRL_FILE = "ca.crl";
    private static final String CA_DELTA_CRL_FILE = "ca_delta.crl";

    public static void main(String[] args) throws IOException {
        // 创建服务器实例，监听8080端口
        HttpServer server = HttpServer.create(new InetSocketAddress(80), 0);

        // 使用单线程池确保OCSP处理顺序执行
        ExecutorService executor = Executors.newSingleThreadExecutor();
        server.setExecutor(executor);

        // 注册路由处理程序
        server.createContext("/", new RootHandler());
        server.createContext("/hello", new HelloHandler());
        server.createContext("/echo", new EchoHandler());
        server.createContext("/ocsp", new OcspHandler()); // 新增OCSP端点
        server.createContext("/ca.crt", new CaCertHandler());
        server.createContext("/ca.crl", new CaCrlHandler());
        server.createContext("/ca_delta.crl", new CaCrlDeltaHandler());

        // 启动服务器
        server.start();
        System.out.println("服务器已启动，访问地址: http://localhost:80/");
    }
    // CA证书处理器
    static class CaCertHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            serveFile(exchange, CA_CERT_FILE, "application/x-x509-ca-cert", "CA证书,ca.crt");
        }
    }

    // CRL处理器
    static class CaCrlHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            serveFile(exchange, CA_CRL_FILE, "application/pkix-crl", "CRL吊销列表,ca.crl");
        }
    }

    // CRL处理器
    static class CaCrlDeltaHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            serveFile(exchange, CA_DELTA_CRL_FILE, "application/pkix-crl", "CRL吊销列表,ca_delta.crl");
        }
    }
    // 通用文件服务方法
    private static void serveFile(HttpExchange exchange, String filename, String contentType, String description) 
        throws IOException {
        
        Path filePath = Paths.get("../SM2Cert/"+filename);
        
        if (!Files.exists(filePath)) {
            String error = description + "文件不存在: " + filename;
            System.err.println(error);
            sendResponse(exchange, error, 404, "text/plain");
            return;
        }
        
        try {
            byte[] fileData = Files.readAllBytes(filePath);
            
            // 设置Content-Disposition头，提示浏览器下载文件
            exchange.getResponseHeaders().set("Content-Disposition", 
                                             "attachment; filename=\"" + filename + "\"");
            
            // 设置内容类型
            exchange.getResponseHeaders().set("Content-Type", contentType);
            
            // 发送响应
            exchange.sendResponseHeaders(200, fileData.length);
            try (OutputStream os = exchange.getResponseBody()) {
                os.write(fileData);
            }
            
            System.out.println("GET:成功发送" + description + " (" + fileData.length + " 字节)");
            
        } catch (IOException e) {
            System.err.println("读取" + description + "文件错误: " + e.getMessage());
            sendResponse(exchange, "服务器内部错误", 500, "text/plain");
        }
    }

    // OCSP响应处理器
    static class OcspHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            // 只接受POST请求
            if (!"POST".equalsIgnoreCase(exchange.getRequestMethod())) {
                sendResponse(exchange, "仅支持POST请求", 405, "text/plain");
                return;
            }

            //执行外部OCSP服务
            Process process = null;
            //使用ProcessBuilder执行外部OCSP服务
            ProcessBuilder pb = new ProcessBuilder(OCSP_CMD);
            pb.redirectErrorStream(true); // 合并错误流到标准输出
            process = pb.start();

            // 检查OCSP响应文件是否存在
            Path ocspPath = Paths.get(OCSP_RESPONSE_FILE);
            if (!Files.exists(ocspPath)) {
                sendResponse(exchange, "OCSP响应文件不存在: " + OCSP_RESPONSE_FILE, 404, "text/plain");
                return;
            }
            
            try {
                // 读取OCSP响应文件内容（二进制格式）
                byte[] ocspResponse = Files.readAllBytes(ocspPath);
                
                // 设置OCSP响应头（标准MIME类型）
                exchange.getResponseHeaders().set("Content-Type", "application/ocsp-response");
                
                // 发送二进制响应
                exchange.sendResponseHeaders(200, ocspResponse.length);
                try (OutputStream os = exchange.getResponseBody()) {
                    os.write(ocspResponse);
                }
                
                System.out.println("POST:成功发送OCSP响应,ocsp.res (" + ocspResponse.length + " 字节)");
            } catch (IOException e) {
                System.err.println("OCSP响应错误: " + e.getMessage());
                sendResponse(exchange, "服务器内部错误", 500, "text/plain");
            }
        }
    }

    // 根路径处理器 (更新包含OCSP链接)
    static class RootHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String response = "<h1>简易Java Web服务端</h1>" +
                             "<ul>" +
                             "<li><a href='/hello'>/hello - 问候接口</a></li>" +
                             "<li><a href='/echo?name=Java'>/echo - 参数回显</a></li>" +
                             "<li><a href='/ocsp'>/ocsp - OCSP响应服务</a> (POST请求)</li>" + // 新增OCSP链接
                             "<li><a href='/ca.crt'>/ca.crt - CA证书下载</a></li>" +
                             "<li><a href='/ca.crl'>/ca.crl - CRL下载</a></li>" +
                             "<li><a href='/ca_delta.crl'>/ca.crl - CRL_DELTA下载</a></li>" +
                             "</ul>";
            sendResponse(exchange, response, 200);
        }
    }

    // 问候接口处理器
    static class HelloHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            String name = getQueryParam(exchange, "name", "访客");
            String response = String.format("{\"message\": \"你好, %s!\"}", name);
            sendResponse(exchange, response, 200, "application/json");
        }
    }

    // 参数回显处理器
    static class EchoHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            Map<String, String> params = parseQuery(exchange.getRequestURI().getQuery());
            
            StringBuilder response = new StringBuilder("<h2>请求参数:</h2><ul>");
            params.forEach((k, v) -> response.append("<li>").append(k).append(": ").append(v).append("</li>"));
            response.append("</ul>");
            
            sendResponse(exchange, response.toString(), 200);
        }
    }

    // 辅助方法：发送响应
    private static void sendResponse(HttpExchange exchange, String response, int code) 
        throws IOException {
        sendResponse(exchange, response, code, "text/html");
    }
    
    private static void sendResponse(HttpExchange exchange, String response, int code, String contentType) 
        throws IOException {
        
        exchange.getResponseHeaders().set("Content-Type", contentType+";charset=utf-8");
        exchange.sendResponseHeaders(code, response.getBytes().length);
        
        try (OutputStream os = exchange.getResponseBody()) {
            os.write(response.getBytes());
        }
    }

    // 辅助方法：解析查询参数
    private static Map<String, String> parseQuery(String query) {
        Map<String, String> params = new HashMap<>();
        if (query == null) return params;
        
        for (String param : query.split("&")) {
            String[] pair = param.split("=");
            if (pair.length > 0) {
                String key = pair[0];
                String value = pair.length > 1 ? pair[1] : "";
                params.put(key, value);
            }
        }
        return params;
    }

    // 辅助方法：获取单个查询参数
    private static String getQueryParam(HttpExchange exchange, String paramName, String defaultValue) {
        String query = exchange.getRequestURI().getQuery();
        if (query == null) return defaultValue;
        
        for (String param : query.split("&")) {
            String[] pair = param.split("=");
            if (pair[0].equals(paramName) && pair.length > 1) {
                return pair[1];
            }
        }
        return defaultValue;
    }
}